/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package earthdawnnet.client;

import earthdawnnet.events.client.ClientEvent;
import earthdawnnet.events.server.LoginEvent;
import earthdawnnet.events.server.LogoutEvent;
import earthdawnnet.events.server.ServerEvent;
import earthdawnnet.util.Chat;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Andreas Franek
 */
public class Client
{

    private Chat chat;
    
    private boolean connected;
    
    public boolean isConnected()
    {
        return connected;
    }

    public Chat getChat()
    {
        return chat;
    }
    private Socket server;
    private EarthdawnNetApp app;
    private ObjectOutputStream out;
    private ObjectInputStream in;
    private ServerData sd;
    private boolean doLoop = true;
    int id;
    
    public int getID()
    {
        return id;
    }

    public Client(Chat chat, EarthdawnNetApp app)
    {
        super();
        connected = false;
        this.app = app;
        this.chat = chat;
        //login();
    }
    
    public void sendServerEvent(ServerEvent se)
    {
        if(!connected) return;
        //System.out.println("Sending line.");
        try
        {
            se.setSender(id);
            out.writeObject(se);
        } catch (IOException ex)
        {
            //Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            connectionClosed();
        }
    }

    public void close()
    {
        if(!connected) return;
        doLoop = false;
        try
        {
            if (in != null) in.close();
            if (out != null) out.close();
            if (server != null) server.close();
        } catch (IOException ex)
        {
            //Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
        } finally
        {
            connected = false;
        }
    }
    
    public void saveNExit()
    {
        ServerData.save();
        User.save();
        logout();
    }
    
    public void logout()
    {
        sendServerEvent(new LogoutEvent());
        close();
    }

    private void connectionClosed()
    {
        close();
        app.connectionClosed();
    }

    public void login()
    {
        doLoop = true;
        try
        {
            sd = ServerData.getInstance();
            //System.out.println("Trying to connect to "+sd.getServerAddress()+":"+sd.getServerPort());
            server = new Socket(sd.getServerAddress(), sd.getServerPort());
            out = new ObjectOutputStream(server.getOutputStream());
            in = new ObjectInputStream(server.getInputStream());
            connected = true;
            newThread();
        } catch (UnknownHostException ex)
        {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            connectionClosed();
        } catch (IOException ex)
        {
            Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
            connectionClosed();
        }
    }

    public void newThread()
    {
        new Thread(new Runnable()
        {
            public void run()
            {
                try
                {
                    id = (Integer)in.readObject();
                    sendServerEvent(new LoginEvent(User.getInstance().getName()));
                } catch (ClassNotFoundException ex)
                {
                    Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IOException ex)
                {
                    Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
                    connectionClosed();
                }
                //System.out.println("Listening...");
                while (doLoop)
                {
                    try
                    {
                        ClientEvent ev = (ClientEvent) in.readObject();
                        ev.apply(app);
                    } catch (IOException ex)
                    {
                        //Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
                        connectionClosed();
                    } catch (ClassNotFoundException ex)
                    {
                        //Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
                        connectionClosed();
                    }
                }
            }
        }).start();
    }
}
